package org.wattdepot.gdata.kukuicup.updater.energylastsevendays;

import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.WattDepotClient;
import org.wattdepot.gdata.kukuicup.service.GDataBatchRequest;
import org.wattdepot.gdata.kukuicup.service.GDataService;
import org.wattdepot.gdata.kukuicup.service.WattDepotService;
import org.wattdepot.gdata.kukuicup.updater.BaselineView;
import org.wattdepot.gdata.kukuicup.updater.GDataCronTask;
import org.wattdepot.util.tstamp.Tstamp;
import it.sauronsoftware.cron4j.TaskExecutionContext;

/**
 * Gets the energy used by a source for each day of the last seven days. 
 * @author Philip Johnson
 */
public class EnergyLastSevenDaysTask extends GDataCronTask {
  
  /**
   * Creates the task that gets woken up once a day to get the daily energy use for the last 7 days.
   * @param wattDepotService The WattDepot service configuration data. 
   * @param gdataService The gdata service configuration data.
   * @param spreadsheetURL The URL to the spreadsheet containing the data.
   * @param sourceName The WattDepot source of interest.
   * @param isVirtual True if the source is virtual.
   * @param row The row in the spreadsheet that this source's data appears in.
   */
  public EnergyLastSevenDaysTask(WattDepotService wattDepotService, GDataService gdataService,
      URL spreadsheetURL, String sourceName, boolean isVirtual, int row) {
    super(wattDepotService, gdataService, spreadsheetURL, sourceName, row, 
        "EnergyLastSevenDays", isVirtual);
  }

  /**
   * The method called once a day to update the data for the last seven days.
   * @param context Ignored.
   * @throws RuntimeException If problems occur (which they shouldn't). 
   */
  @Override
  public void execute(TaskExecutionContext context) throws RuntimeException {
    // Need to deal with missing data, like when sensors are not working. 
    System.out.format("Running EnergyLastSevenDays for source %s%n", sourceName);

    // Get the current time. 
    XMLGregorianCalendar currTime = Tstamp.makeTimestamp();

    // Get the daily energy values for the past seven days.
    startWattDepotTiming();
    List<String> energies = getDailyEnergy(currTime);
    stopWattDepotTiming();

    startGDataTiming();

    // Get the baseline data.
    BaselineView baselineView = new BaselineView(this.gdataService);
    int startDay = currTime.toGregorianCalendar().get(Calendar.DAY_OF_WEEK);
    List<String> baselines = baselineView.getDailyBaselines(sourceName, startDay);
    
    // Add the actual data to the spreadsheet.
    GDataBatchRequest request = new GDataBatchRequest(gdataService, spreadsheetURL);
    try {
      // Add the last update field
      request.addRequest(this.row, 2, gdataService.makeLastUpdate(currTime));
      // Add the actual energy data. 
      for (int i = 0; i < 7; i++) {
        request.addRequest(this.row, i + 3, energies.get(i)); 
      }
      int column = 10;
      for (String baseline : baselines) {
        request.addRequest(this.row, column, baseline);
        column++;
      }
      // Send the request.
      request.sendRequest();
    }
    catch (Exception e) {
      System.out.println("Error making batch request for source " + this.sourceName);
      e.printStackTrace();
    }
    stopGDataTiming();
    printTaskResults("Last 7", "kWh", "OK");
  }
  
  /**
   * Returns a list with the 7 days of daily energy prior to the passed timestamp.  
   * @param currTime The time that we go backward from. 
   * @return A list of 7 integers containing daily energy for a 24 hour period. 
   */
  private List<String> getDailyEnergy(XMLGregorianCalendar currTime) {
    WattDepotClient client = this.wattDepotService.getClient();
    List<String> energies = new ArrayList<String>();
    // Make a new timestamp for the previous day with hours, mins, secs, and millisecs set to zero.
    XMLGregorianCalendar startDay = Tstamp.incrementDays(currTime, -7);
    startDay.setHour(0);
    startDay.setMinute(0);
    startDay.setSecond(0);
    startDay.setMillisecond(0);
    // Now gather the energy data from the past seven days and add to spreadsheet.
    for (int i = 0; i < 7; i++) {
      XMLGregorianCalendar begin = Tstamp.incrementDays(startDay, i);
      XMLGregorianCalendar end = Tstamp.incrementDays(startDay, i + 1);
      Integer energy = 0;
      try {
        energy = (int) client.getEnergyConsumed(sourceName, begin, end, 10);
      }
      catch (Exception e) {
        System.out.format("Failed to get energy for %s for day %s, %s%n", sourceName, begin, 
            e.getMessage());
      }
      energies.add(String.valueOf(energy));
    }
    return energies;
  }

}
